#! /Library/Frameworks/Python.framework/Versions/Current/bin/python 

import array, getopt, sys, commands, string, tempfile, os, shutil, re, Image, ImageColor, ImageFilter, difflib
import RasterDiff

def main(argv):                         
	output_file = "diffdoc_out.png"

	global _cwd, _verbose, _input_filetype, _line_height
	_cwd = os.getcwd()
	_verbose = False
	_line_height = 20

	try:                                
		opts, args = getopt.getopt(argv, "hvo:", ["help", "output=", "line-height="])
	except getopt.GetoptError:
		usage()
		sys.exit(2)

	for opt, arg in opts:                
		if opt in ("-h", "--help"):      
			usage()                     
			sys.exit()                  
		elif opt == '-v':
			_verbose = True
		elif opt == '-d':
			global _debug
			_debug = 1     

		elif opt in ("-o", "--output"): 
			output_file = arg

		elif opt == "--line-height": 
			_line_height = int( arg )


	if len( sys.argv ) == 1:
		raise Exception( 'No input files specified!' );

	elif len( sys.argv ) == 2:
		raise Exception( 'Only one input file specified!' );

	file_a = sys.argv[-2]
	file_b = sys.argv[-1]

	_input_filetype = os.path.splitext( file_a )
	_input_filetype = _input_filetype[-1]
	print "input filetype: " + _input_filetype

	# (assume file is a doc ) 

	file_a_png = find_current_png_file( file_a )

	if file_a_png == None:
		file_a_png = file2png( file_a )

	print "file_a_png: " + file_a_png

	file_b_png = find_current_png_file( file_b )

	if file_b_png == None:
		file_b_png = file2png( file_b )


	im_a = Image.open( file_a_png )
	im_a.load()

	im_b = Image.open( file_b_png )
	im_b.load()

	rd = RasterDiff.RasterDiff( im_a, im_b )
	rd.verbose = _verbose
	rd.line_height = _line_height

	output_im = rd.compute_diff( ) 

	output_filename = string.replace( file_b, _input_filetype, '_diff.png' )

	if os.path.exists( output_filename ):
		os.remove( output_filename )

	output_im.save( output_filename )
	print "output file: " +  output_filename


def image_cleanup( im ):
	# remove blank borders 

	im2 = im.crop( im.getbbox() )
	im2 = im2.convert( '1' )
	im2.load()
	return im2



def file2png( file_path, tempdir = None ):
	global _input_filetype, _cwd, _verbose

	if _input_filetype == '.doc':
		return doc2png( file_path, tempdir )
	elif _input_filetype == '.pdf':
		return pdf2png( file_path, tempdir )

def doc2png( file_path, tempdir = None ):

	global _verbose, _cwd, _input_filetype

	print file_path

	file_name = os.path.basename( file_path )

	# create tempdir, copy file there
	if tempdir == None:
		tempdir = tempfile.mkdtemp()

	shutil.copyfile( file_path, tempdir + '/' + file_name )

	# convert doc to rtf

	if _verbose:
		print "Converting to rtf..."

	cmd = 'textutil -convert rtf '+ tempdir + '/'+ file_name 
	(status, output) = commands.getstatusoutput( cmd )

	print status
	print output

	# convert rtf to pdf

	if _verbose:
		print "Converting to pdf..."

	cmd = '/System/Library/Printers/Libraries/convert -f ' + tempdir + '/' + string.replace( file_name, _input_filetype, '.rtf' ) + ' -o ' + tempdir + '/' + string.replace( file_name, _input_filetype, '.pdf' ) 
	print cmd
	(status, output) = commands.getstatusoutput( cmd )
	print status
	print output


	pdf_file_name = string.replace( file_name, _input_filetype, '.pdf' )

	return pdf2png( pdf_file_name, tempdir )


def pdf2png( pdf_file_name, tempdir ):

	global _verbose, _cwd, _input_filetype

	# create tempdir, copy file there
	if tempdir == None:
		tempdir = tempfile.mkdtemp()
		shutil.copyfile( pdf_file_name, tempdir + '/' + pdf_file_name )

	os.mkdir( tempdir + '/pdf_pages' )
	os.mkdir( tempdir + '/png_pages' )

	png_file_name = string.replace( pdf_file_name, '.pdf', '.png' )

	# convert pdf to single-page pdfs

	cmd = 'automator -v -i ' + tempdir + '/' + pdf_file_name + ' -D output_path=' + tempdir +  '/pdf_pages ' + _cwd  + '/pdf2images.workflow'
	print cmd
	(status, output) = commands.getstatusoutput( cmd )
	print status
	print output

	# convert single-page pdfs to pngs

	single_pdfs = os.listdir( tempdir + '/pdf_pages' )

	page_index = 0

	single_pdfs.sort( cmp=file_number )
	for single_pdf in single_pdfs:
		cmd = 'sips -s format png "' + tempdir + '/pdf_pages/' + single_pdf + '" --out ' + tempdir + '/png_pages/page_' + str( page_index ) + '.png'
		page_index += 1
		(status, output) = commands.getstatusoutput( cmd )
		print status
		print output

	# vertically concatenate pngs

	single_pngs = os.listdir( tempdir + '/png_pages' )
	single_pngs.sort( cmp=file_number )

	images = map(Image.open, [ tempdir + '/png_pages/' + f for f in single_pngs ] )

	cleaned_images = []
	for im in images:
	  cleaned_images.append( image_cleanup( im ) )

	result = RasterDiff.vcat_images( cleaned_images, "1" )

	result.save( tempdir + '/' + png_file_name )

	shutil.copyfile( tempdir + '/' + png_file_name, _cwd + '/' + png_file_name ) 
	result = None

	return png_file_name



def file_number(x, y):
	xr = x[::-1]
	yr = y[::-1]

	xnum = re.search( '\d+', xr )
	xnum = xnum.group(0)

	ynum = re.search( '\d+', yr )
	ynum = ynum.group(0)

	xnumr = xnum[::-1]
	ynumr = ynum[::-1]

	return int(xnumr) - int(ynumr)

def find_current_png_file( file_path ):
	global _input_filetype, _verbose, _cwd

	png_file_name = string.replace( file_path, _input_filetype, '.png' )

	print "png_file_name: " + png_file_name

	if ( os.path.exists( _cwd + '/' + png_file_name ) ):
		if _verbose:
			print "Using existing file: " + png_file_name
		return png_file_name

	return None

def usage():
	print """
diffdoc [options] file1 file2

	--line-height (default 20) minimum line height (in pixels) for changes to be recognized

"""


if __name__ == "__main__":
    main(sys.argv[1:])

